package cn.mw.cmdb.entity;

import cn.mw.cmdb.param.ImportContextParam;
import cn.mw.cmdb.param.InstanceSearchParam;
import cn.mw.cmdb.service.impl.CmdbServiceManage;
import cn.mw.cmdb.service.impl.CustomModelServiceImpl;
import cn.mw.cmdb.service.impl.InstanceServiceImpl;
import cn.mw.components.mongodb.entity.CriteriaOpsType;
import cn.mw.microMonitorCommon.entity.cmdb.ModelExportDataInfoParam;
import cn.mw.microMonitorCommon.entity.cmdb.MwImportResultParam;
import cn.mw.microMonitorCommon.util.SpringUtils;
import com.google.common.base.Strings;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static cn.mw.cmdb.service.impl.InstanceViewImpl.*;

@Slf4j
public class PropertyTypeEnumSingle extends PropertyType<PropertyTypeEnumSingle, Object> {
    public static final String ID = "enumSingle";
    private static final String FirstDropdownKey = "modelId";
    public static final String enumInfoListKey = "enumInfoList";
    public static final String defaultValueKey = "value";

    private static List<String> finalList = new ArrayList<>();
    //枚举下拉数据
    private List enumInfoList;
    private static final String SecodDropdownKey = "fieldId";

    public PropertyTypeEnumSingle() {
        setId(ID);
        setName("枚举类型(单选)");
        setSortNum(9);
    }

    @Override
    public Object tableHeaderTipInfo(PropertyTypeRef propertyTypeRef) {
        String tipInfo = "";
        if (propertyTypeRef != null && propertyTypeRef.getContext() != null) {
            Map<String, Object> context = propertyTypeRef.getContext();
            Object obj = context.get(enumInfoListKey);
            Object defaultVal = context.get(defaultValueKey);
            if (obj != null && obj instanceof List) {
                List<String> listStr = (List<String>) obj;
                tipInfo += String.join(",", listStr);
                if (!Strings.isNullOrEmpty(strValueConvert(defaultVal))) {
                    tipInfo += ";默认值:" + strValueConvert(defaultVal) + ",";
                }
            }
        }
        return tipInfo;
    }


    @Override
    public boolean tableHeaderInfo(Map ms, PropertyInfo propertyInfo, List<String> labelNames, List<String> labelId) {
        //导出表头数据时，表头字段的id和名称不能同时重复
        if ((labelId != null && !labelId.contains(propertyInfo.getId())) && (labelNames != null && !labelNames.contains(ms.get(nameKey)))) {
            ms.put(typeKey, PropertyTypeEnumSingle.ID);
            if (propertyInfo.getPropertyTypeRef() != null && propertyInfo.getPropertyTypeRef().getContext() != null) {
                PropertyTypeRef propertyTypeRef = propertyInfo.getPropertyTypeRef();
                Map<String, Object> context = propertyTypeRef.getContext();
                Object obj = context.get(enumInfoListKey);
                if (obj != null && obj instanceof List) {
                    List<String> listStr = (List<String>) obj;
                    ms.put(selectDataKey, listStr);
                }
                labelId.add(propertyInfo.getId());
                return true;
            }
        }
        return false;
    }

    @Override
    public Criteria doCriteria(CriteriaOpsType opsType, String name, Object value) {
        Criteria criteria = null;
        switch (opsType) {
            case is:
                criteria = new Criteria(name).is(value == null ? null : value.toString());
                break;
            case in:
                if (value instanceof List) {
                    Object[] objects = ((List) value).toArray();
                    criteria = new Criteria(name).in(objects);
                } else {
                    criteria = new Criteria(name).in(value);
                }
                break;
            case nin:
                if (value instanceof List) {
                    Object[] objects = ((List) value).toArray();
                    criteria = new Criteria(name).nin(objects);
                } else {
                    criteria = new Criteria(name).nin(value);
                }
                break;
            case regex:
                criteria = new Criteria(name).regex(value.toString());
                break;
            case like:
                Pattern pattern = Pattern.compile(regexCharacters(value), Pattern.CASE_INSENSITIVE);
                criteria = new Criteria(name).regex(pattern);
                break;
            case notLike:
                Pattern pattern1 = Pattern.compile(regexCharacters(value), Pattern.CASE_INSENSITIVE);
                criteria = new Criteria(name).not().regex(pattern1);
                break;
            case exist:
                criteria = new Criteria(name).exists((boolean) value);
                break;
            case ne:
                criteria = new Criteria(name).ne(value);
        }
        return criteria;
    }

    @Override
    public CriteriaOpsType getDefaultCriteriaOpsType() {
        return CriteriaOpsType.is;
    }

    @Override
    public PropertyTypeEnumSingle newObj() {
        return new PropertyTypeEnumSingle();
    }

    @Override
    public Object listInputOption(PropertyTypeRef propertyTypeRef) throws Exception {
        Map<String, Object> context = propertyTypeRef.getContext();
        List<InstanceInputOption> list = new ArrayList<>();
        if (null != context) {
            CmdbServiceManage cmdbServiceManage = SpringUtils.getBean(CmdbServiceManage.class);
            InstanceServiceImpl instanceService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
            InstanceSearchParam searchParam = new InstanceSearchParam();

            String modelId = context.get(FirstDropdownKey).toString();
            String propertyId = context.get(SecodDropdownKey).toString();

            if (StringUtils.hasText(modelId)) {
                searchParam.setModelId(modelId);
                List<InstanceInfo> instanceInfoList = instanceService.selectList(searchParam);
                if (StringUtils.hasText(propertyId) && null != instanceInfoList) {
                    for (InstanceInfo instanceInfo : instanceInfoList) {
                        InstanceInputOption inputOption = new InstanceInputOption(instanceInfo.getId(), instanceInfo.getValue(propertyId).toString());
                        list.add(inputOption);
                    }
                } else {
                    CustomModelServiceImpl customModelService = (CustomModelServiceImpl) cmdbServiceManage.getModelService(CustomModelServiceImpl.ID);
                    List<ModelInfo> modelInfos = customModelService.findAllList();
                    for (ModelInfo modelInfo : modelInfos) {
                        InstanceInputOption inputOption = new InstanceInputOption(modelInfo.getId(), modelInfo.getModelName());
                        list.add(inputOption);
                    }
                }
            }
        }

        return list;
    }

    @Override
    public void refresh() {
        finalList.clear();
    }


    @Override
    public Object lookValue(Object val, Map<String, Object> context) {
        if (val != null && val instanceof String) {
            return strValueConvert(val);
        }
        return val;
    }

    /**
     * 获取新增字段所需要的配置数据
     *
     * @param val
     * @param context
     * @return
     */
    @Override
    public Object getDefaultInputValue(Object val, Map<String, Object> context) {
        if (context != null) {
            return context;
        }
        return null;
    }


    @Override
    public Object getDataValue(ImportContextParam contextParam) throws Exception {
        CmdbServiceManage cmdbServiceManage = SpringUtils.getBean(CmdbServiceManage.class);
        InstanceServiceImpl modelService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
        MwImportResultParam resultParam = new MwImportResultParam();
        List<PropertyInfo> modelPropertyList = contextParam.getModelPropertyList();
        Map<String, PropertyInfo> collect = new HashMap<>();
        if(modelPropertyList!=null){
            collect = modelPropertyList.stream().collect(Collectors.toMap(s -> s.getId(), s -> s, (
                    value1, value2) -> {
                return value2.getPropertySource() == null ? value2 : value1;
            }));
        }
        ModelExportDataInfoParam importParam = contextParam.getParam();
        String relationModelId = importParam.getRelationModelId();
        PropertyInfo propertyInfo = new PropertyInfo();
        //属性id
        String propertyId = importParam.getPropertyId();
        List<String> listStr = new ArrayList<>();
        Object defaultVal = null;
        String message = "";
        //属性名称
        String tableName = importParam.getTableName();
        Object cellValue = importParam.getCellValue();
        Map<String, Object> matchMap = new HashMap<>();
        importCheckInfo(resultParam, contextParam, matchMap);

        if (collect != null && collect.containsKey(propertyId)) {
            propertyInfo = collect.get(propertyId);
            if (propertyInfo.getPropertyTypeRef() != null && propertyInfo.getPropertyTypeRef().getContext() != null) {
                Map<String, Object> context = propertyInfo.getPropertyTypeRef().getContext();
                //枚举下拉值
                Object obj = context.get(enumInfoListKey);
                //默认值
                defaultVal = context.get(defaultValueKey);
                if (obj != null && obj instanceof List) {
                    listStr = (List<String>) obj;
                }
            }

        }
        log.info(tableName + ":extSingle::" + cellValue);

        List<InstanceInfo> instanceInfoList = modelService.doListByModelIdsNotAuth(Arrays.asList(relationModelId));
        Map<String, String> instanceNameById = instanceInfoList.stream().filter(s -> !Strings.isNullOrEmpty(s.getInstanceName())).collect(Collectors.toMap(s -> s.getInstanceName(), s -> s.getId(), (
                value1, value2) -> {
            return value2;
        }));


        String cellValStr = strValueConvert(cellValue);
        if (CollectionUtils.isNotEmpty(listStr)) {
            if (!listStr.contains(cellValStr) && !Strings.isNullOrEmpty(cellValStr.trim())) {
                message += tableName + "枚举值不存在";
                resultParam.setMessage(message);
                return resultParam;
            }
            //枚举数据未选，指定默认值了
            if (Strings.isNullOrEmpty(cellValStr) && !Strings.isNullOrEmpty(strValueConvert(defaultVal))) {
                cellValStr = strValueConvert(defaultVal);
            }
        }
        resultParam.setCellValue(cellValStr);
        return resultParam;
    }

}
